package com.token.sysflow.hander;
import com.alibaba.fastjson.JSONObject;
import com.token.base.Pl;
import com.token.sql.IntegrateSql;
import com.token.sql.PrepareSql;
import com.token.sql.TableBeanPrepareSql;
import com.token.sysflow.bean.*;
import com.token.sysflow.enumerate.ApprovalTypeEnum;
import com.token.sysflow.enumerate.FlowStatusEnum;
import com.token.sysflow.enumerate.FlowTypeEnum;
import com.token.sysflow.exception.ErrorCodeEnum;
import com.token.sysflow.exception.FlowException;
import com.token.sysflow.impl.SubmitFlowImpl;
import com.token.sysorg.bean.FSysPersonnel;
import com.token.sysorg.bean.FSysPost;
import com.token.sysorg.bean.fsysroleMember;

import java.sql.ResultSet;
import java.util.ArrayList;
import java.util.HashMap;


/**
 * @author chenjianxiong 2020/6/2
 */
public class SubFlow {
    private final FlowStepSubflow stepSubflow;
    private final FlowStepSubflowSub subflowSub;

    public SubFlow(IntegrateSql iSql, String toStepId) throws Exception {
        stepSubflow = new FlowStepSubflow(iSql, toStepId);
        subflowSub = new FlowStepSubflowSub(iSql);
    }

    /**
     * 初始化子流程
     *
     * @return true 是
     */
    public boolean getSubflowReSave() {
        return stepSubflow.getSubflowReSave().equals("1");
    }

    /**
     * 子流程行项目
     *
     * @return ResultSet
     * @throws Exception 抛出错误
     */
    private ResultSet getSubflowSub() throws Exception {
        TableBeanPrepareSql tSql = new TableBeanPrepareSql(subflowSub);
        tSql.setSelectPrepare(" StepId=? ");
        tSql.setPstValue(1, stepSubflow.getStepId());
        return tSql.executeQuery();
    }

    /**
     * 获取子流程办理人
     *
     * @return [{approver:[],subName:"",subId:""}]
     * @throws Exception
     */
    public ArrayList<JSONObject> getFlowSubApprovers() throws Exception {
        ArrayList<JSONObject> arrayList = new ArrayList<>() ;
        ResultSet rs = this.getSubflowSub();
//        StringBuilder buffer = new StringBuilder(50);
//        boolean isHas = false;
        JSONObject json;
        HashMap<String, JSONObject> map = new HashMap<>();
        if (rs.next()) {
            do {
                subflowSub.initParamToRs(rs);
//                System.out.println("subflowSub = " + subflowSub.getSubFlowName());
                if (isAvailable()) {
//                    if (isHas) {
//                        buffer.append(",");
//                    }
                    json = new JSONObject();
                    json.put("subName", subflowSub.getSubFlowName());
                    json.put("subId", subflowSub.getKeyId());
//                    buffer.append("'").append(subflowSub.getKeyId()).append("'");
                    map.put(subflowSub.getKeyId(), json);  //<subFlowId,{name,id}>
//                    isHas = true;

                    //计算出办理人
                    if(!this.approverPeoples(arrayList,map,subflowSub.getKeyId())){
                        if(!this.approverRoles(arrayList,map,subflowSub.getKeyId())){
                            throw new FlowException(ErrorCodeEnum.SUBFLOW_APPROVER_NOFIND,subflowSub.getSubFlowName());
                        }
                    }

                }

            } while (rs.next());
        }
        rs.close();


        return arrayList;
    }

    /**
     * 读取子流程办理人
     * @param map subFlowId:{subName:"",subId:""}
     * @param subFlowId 子流程配置Id
     * @return true 有办理人
     * @throws Exception 抛出错误
     */
    private boolean approverPeoples(ArrayList<JSONObject> arrayList,HashMap<String, JSONObject> map,String subFlowId) throws Exception{
        boolean isHas = false;
        PrepareSql pSql = new PrepareSql(subflowSub.getIntegrateSql());
        StringBuffer sql = new StringBuffer(100);
        sql.append("select vth.Value,vth.SubFlowId from ")
                .append(FlowStepSubflowVth.TABLE_NAME)
                .append(" vth ")
                .append(" where vth.FieldName=? and vth.SubFlowID=?")
                .append(" order by vth.SubFlowID ");
        pSql.setPrepare(sql);
        pSql.setPstValue(1, "ApproverPeoples");
        pSql.setPstValue(2, subFlowId);
        ResultSet rs = pSql.executeQuery();
        if (rs.next()) {
            isHas = true;
            addArrayList(rs,arrayList,map);
        }
        rs.close();
        return isHas;
    }

    /**
     *
     * @param rs 结果集
     * @param arrayList 组数
     * @param map subFlowId:{subName:"",subId:""}
     * @throws Exception 抛出错误
     */
    private void addArrayList(ResultSet rs,ArrayList<JSONObject> arrayList,HashMap<String, JSONObject> map)throws Exception{
        String subflowId = rs.getString("SubFlowId");
        JSONObject json = map.get(subflowId);
        ArrayList<String> apprvoer = new ArrayList<>();
        do {
            if (!subflowId.equals(rs.getString("SubFlowId"))) {
                json.put("approver", apprvoer);
                arrayList.add(json);

                subflowId = rs.getString("SubFlowId");
                json = map.get(subflowId);
                apprvoer = new ArrayList<>();
            }
            apprvoer.add(rs.getString("Value"));
        } while (rs.next());
        if (apprvoer.size() > 0) {
            json.put("approver", apprvoer);
            arrayList.add(json);
        }
    }
    /**
     * 读取子流程角色
     * @param map subFlowId:{subName:"",subId:""}
     * @param subFlowId 子流程配置Id
     * @return true
     */
    private boolean approverRoles(ArrayList<JSONObject>  arrayList,HashMap<String, JSONObject> map,String subFlowId) throws Exception{
        boolean isHas = false;
        PrepareSql pSql = new PrepareSql(subflowSub.getIntegrateSql());
        StringBuffer sql = new StringBuffer(100);

        //配置-->角色成员
        sql.append("select member.RoleMemberNumber as Value,vth.SubFlowId from ")
                .append(FlowStepSubflowVth.TABLE_NAME) // 配置
                .append(" vth inner join ")
                .append(fsysroleMember.TABLE_NAME) // 角色成员
                .append(" member on vth.value = member.RoleNumber")
                .append(" where member.SysId=? and vth.FieldName=? and vth.SubFlowID=? and member.RoleMemberType=2 "); //人员
        sql.append(" UNION ALL ");

        //配置-->角色成员-->岗位-->人员
        sql.append("select user.PersonNumber as Value,vth.SubFlowId from ")
                .append(FlowStepSubflowVth.TABLE_NAME) // 配置
                .append(" vth inner join ")
                .append(fsysroleMember.TABLE_NAME) // 角色成员
                .append(" member on vth.Value = member.RoleNumber ")
                .append(" inner join ")
                .append(FSysPost.TABLE_NAME) //岗位
                .append(" post on member.RoleMemberNumber=post.PostNumber and member.SysId=post.SysId ")
                .append(" inner join ")
                .append(FSysPersonnel.TABLE_NAME) //人员
                .append(" user on member.RoleMemberNumber = user.PostId and user.SysId=member.SysId")
                .append(" where member.SysId=? and vth.FieldName=? and vth.SubFlowID=? and member.RoleMemberType=1"); //岗位
        pSql.setPrepare(sql);
        pSql.setPstValue(1, Pl.getSysId());
        pSql.setPstValue(2, "ApproverRoles");
        pSql.setPstValue(3, subFlowId);
        pSql.setPstValue(4, Pl.getSysId());
        pSql.setPstValue(5, "ApproverRoles");
        pSql.setPstValue(6, subFlowId);
        ResultSet rs = pSql.executeQuery();

        if (rs.next()) {
            isHas = true;
            addArrayList(rs,arrayList,map);
        }
        rs.close();
        return isHas;
    }
    /**
     * @return true
     */
    public boolean isAvailable() {
        //TODO 计算子流程是否可用。
        return subflowSub.getReturnResult().equals("1") || "".equals(subflowSub.getReturnResult());
    }

    /**
     * 创建子流程审批数据
     * @param step       目标环节
     * @param flowImpl 参数
     * @param mainProcess 主文档的审批数据
     * @throws Exception 抛出错误
     */
    public void createFlowSubApproveProcess(Step step, SubmitFlowImpl flowImpl, ApproveProcess mainProcess) throws Exception {
        String[] subflow = flowImpl.getSelectApprover();
        String actionUser = flowImpl.getActionUser();
        ApproveProcess subProcess = new ApproveProcess(stepSubflow.getIntegrateSql());
        subProcess.setInsert();
        subProcess.setParentId(mainProcess.getKeyUnid());
        subProcess.setParentStepId(step.getStepId()); //父节点
        subProcess.setSysId(mainProcess.getSysId()); //租户ID
        subProcess.setSysAddTime(Pl.getCurDataTime()); //创建时间
        subProcess.setSysAddUser(actionUser); //创建人
        subProcess.setSysEditTime(Pl.getCurDataTime()); //修改时间
        subProcess.setSysEditUser(actionUser); //修改人
        subProcess.setAppKeyId(mainProcess.getAppKeyId()); //关联应用编号
        subProcess.setCreater(mainProcess.getCreater()); //创建人
        subProcess.setApplyer(mainProcess.getApplyer()); //申请人
        subProcess.setFlowStatus(FlowStatusEnum.START.getId()); //当前流程状态
        subProcess.setApprovalType(ApprovalTypeEnum.SP.getId());
        subProcess.setFlowType(FlowTypeEnum.SUB_FLOW.getId());
        subProcess.setFlowNo(mainProcess.getFlowNo());
        Flow flow = null;
        for(String select:subflow){ //SubFlow1591069083001-2509|100001,100003
            String[] splitStr = select.split("\\|");
            if (subflowSub.initParamToRs(splitStr[0])) { //子流程的配置存在
                if(subflowSub.getSelectSubFlow().equals("")){
                    throw new FlowException(ErrorCodeEnum.FLOWSUB_FLOWID_NOFIND);
                }

                //子流程不相同时。重新获取流程对象。
                if(flow != null) {
                    if (!flow.getFlowId().equals(subflowSub.getSelectSubFlow())) {
                        flow.close();
                        flow = new Flow(stepSubflow.getIntegrateSql(), subflowSub.getSelectSubFlow());
                    }
                }else {
                    flow = new Flow(stepSubflow.getIntegrateSql(), subflowSub.getSelectSubFlow());
                }

                if (!flow.isHas()) {//流程Id不存在，提示子流程不存在
                    throw new FlowException(ErrorCodeEnum.SUBFLOW_NOFIND_ERROR, subflowSub.getSelectSubFlow());
                }else{
                    if(!flow.isActive()){
                        throw new FlowException(ErrorCodeEnum.SUBFLOW_NOACTIVE,subflowSub.getSelectSubFlow());
                    }
                }

                subProcess.setFlowId(subflowSub.getSelectSubFlow()); //子流程的流程Id
                subProcess.setSubject(subflowSub.getSubFlowName());
                Step subStep = flow.getStartStep();
                subProcess.setStepId(subStep.getStepId()); //子流程环节ID
                subProcess.setKeyUnid(Pl.getUuid()); //单据关联ID
                subProcess.executeUpdate();

                //写入子流程的办理人
                String[] approvers = splitStr[1].split(",");


//                mainProcess.addToStepApprover(subProcess.addToStepApprover(approvers));
                //写入子流程的办理人
                subProcess.addToStepApprover(approvers);

                //同时写一份数据到主流程的办理人中，不然审批中的列表出不来数据
//                mainProcess.addStepApproverToMain(subProcess.getKeyId());

                mainProcess.appendFlowProcessInfo(flow,subStep,subProcess);

                subStep.close();
                flow.close();
            } else {
                throw new FlowException(ErrorCodeEnum.FLOWSUB_NOFIND_ERROR);
            }
        }

        subProcess.close();
    }

    /**
     *
     */
    public void close() {
        try {
            stepSubflow.close();
            subflowSub.close();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}
